home *** CD-ROM | disk | FTP | other *** search
- /*
- ** linux/atari/atacon.c
- **
- ** Copyright (C) 1993 Bjoern Brauel and Roman Hodek
- **
- **
- ** This file is subject to the terms and conditions of the GNU General Public
- ** License. See the file README.legal in the main directory of this archive
- ** for more details.
- */
-
- #include <linux/types.h>
- #include <linux/fs.h>
- #include <linux/kernel.h>
- #include <linux/tty.h>
- #include <linux/console.h>
- #include <linux/string.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/bootinfo.h>
- #include <linux/delay.h>
-
- #include <linux/malloc.h>
- #include <linux/mm.h>
-
- #include <linux/atarihw.h>
- #include <linux/atariints.h>
-
- #include <asm/system.h>
-
- /* The following symbols select what modes are supported. They should
- * be settable by the user ("make config") later.
- * True color (= 16 plane) mode isn't implemented yet!
- */
- #define CONFIG_ATARI_2PLANE
- #define CONFIG_ATARI_4PLANE
- #define CONFIG_ATARI_8PLANE
- #undef CONFIG_ATARI_16PLANE
-
- /* To do:
- *
- * - Do proper Falcon video mode setting, analogous to the TT (but
- * much more and better modes possible!)
- * - Implement 16 plane mode.
- * - Do a backing store of characters and attributes on the screen
- * for conole switching (or will this be done in the device
- * independent part (console.c) ?)
- *
- */
-
-
- /*
- ** Macros
- */
-
-
- /* Define if the font contains all 256 characters (undefined: only
- * 32..127 and 160..255, this is the font in font.c of the Amiga
- * distribution)
- */
-
- #define WHOLE_FONT
-
- static unsigned long mem_req;
-
- /* There is no support for fontwidth != 8 now!! (And I guess, it will
- * never come; who needs such stuff??)
- */
-
- extern unsigned char
- fontdata_8x16[], fontdata_8x8[];
-
- extern int
- fontheight_8x16, fontheight_8x8,
- fontwidth_8x16, fontwidth_8x8;
-
- extern char
- fontname_8x16[], fontname_8x8[];
-
-
-
-
-
- /* FONT_CNV does the character conversion necessary if the font
- * doesn't contain all characters. It returns 0 if the characters is
- * not in the font (WHOLE_FONT undefined).
- *
- * If we have a full font, FONT_CNV has to do the jobs of translating
- * the character to be printed according to the console's current
- * translation table. This is just a quick hack to enable the
- * different translations (normal, graphic, ...) that VT102 allows. It
- * should really be done in console.c, where it is commented out
- * currently, and I didn't want to interfere with the people
- * maintaining that code.
- * Roman
- */
-
- #ifndef WHOLE_FONT
-
- #define FONT_CNV(c) ({
- int __rv = 1;
- if ((c >= 32) && (c < 127))
- /* lower half of charset -- normal ASCII */
- c -= 32;
- else if ((c >= 160) && (c < 255))
- /* upper half of charset -- special characters */
- c -= 64;
- else
- /* not defined in charset -- non-printable character */
- __rv = 0;
- __rv;
- })
-
- #else
-
- #define FONT_CNV(c) ((c = conp->vc_translate[c]) != 0)
-
- #endif
-
-
- /*
- ** Local Variables
- */
- struct tt_vid_type
- {
- const char *name;
- ushort xres;
- ushort yres;
- ushort depth;
- };
-
- struct falcon_vid_type
- {
- const char *name;
- };
-
- struct display;
-
- struct display_switch {
- void (*bmove)( register struct display *p, int sy, int sx, int dy,
- int dx, int height, int width);
- void (*clear)( struct condata *conp, register struct display *p,
- int sy, int sx, int height, int width);
- void (*putc)( struct condata *conp, struct display *p, int c,
- int y, int x, int mode );
- void (*putcs)( struct condata *conp, struct display *p,
- const char *s, int count, int y, int x, int mode);
- void (*rev_char)( struct display *display, int x, int y );
- };
-
- struct display
- {
- ushort scr_height; /* screens dimensions */
- ushort scr_width;
- ushort scr_depth; /* # planes */
- ushort bytes_per_row; /* offset to one line below; if (scr_depth
- * != 1), this is (scr_width / 8 *
- * scr_depth)! */
- ushort cursor_x; /* current cursor position */
- ushort cursor_y;
-
- ushort shiftmode; /* display mode */
-
- ushort fgcol; /* text colors */
- ushort bgcol;
-
- u_char *bitplane; /* pointer to display bitmap; planes
- * are interleaved!
- */
- u_long *color_map; /* XXX Not yet implemented XXX */
-
- u_char *fontdata; /* Font associated to this display */
- ushort fontheight;
- ushort fontwidth;
-
- struct display_switch *dispsw; /* pointers to depth specific
- * functions
- */
- };
-
- static struct display disp[NR_CONSOLES];
-
- static struct tt_vid_type tt_video_modes[TT_SHIFTER_NUMMODE] = {
- { "stlow", 320 , 200 , 1 } , /* ST-Low */
- { "stmid", 640 , 200 , 2 } , /* ST-Mid */
- { "sthigh", 640 , 400 , 1 } , /* ST-High */
- { "", 000 , 000 , 0 } , /* unused */
- { "ttmid", 640 , 480 , 4 } , /* TT-Mid */
- { "", 000 , 000 , 0 } , /* unused */
- { "tthigh", 1280 , 960 , 1 } , /* TT-High */
- { "ttlow", 320 , 480 , 8 } }; /* TT-Low */
-
- static struct tt_vid_type falcon_video_modes[] = {
- { "sthigh" }
- };
-
- /* Default color maps for 4 and 2 plane modes. These use the PC-ish
- * assignment (the low 3 bits turn each RBG channel on/off, the 4th
- * bit is intensity). Currently, 8 plane mode uses the 4 plane color
- * table, too.
- */
-
- u_short default_16_colors[16] = {
- 0x000, /* black */
- 0x00c, /* blue */
- 0x0c0, /* green */
- 0x0cc, /* cyan */
- 0xc00, /* red */
- 0xc0c, /* magenta */
- 0xcc0, /* brown */
- 0xccc, /* light gray */
- 0x888, /* gray */
- 0x00f, /* light blue */
- 0x0f0, /* light green */
- 0x0ff, /* light cyan */
- 0xf00, /* light red */
- 0xf0f, /* light magenta */
- 0xff0, /* light brown */
- 0xfff /* white */
- };
-
- /* The 4 colors of 2 plane mode are used as a grey scale to implement
- * the vc_intensity == 0 or == 2 modes.
- */
-
- u_short default_4_colors[4] = {
- 0x000, /* black */
- 0xccc, /* light gray */
- 0x888, /* gray */
- 0xfff /* white */
- };
-
-
- static int cursor_drawn = 0;
-
- static int atacon_default_font = -1;
- static int atacon_default_shiftmode = -1;
-
-
- #undef CURSOR_DELAY_TIMER
- #define CURSOR_DELAY_VBL
-
- #ifdef CURSOR_DELAY_TIMER
-
- /* Time to elapse before the cursor is really drawn, in jiffies */
- #define CURSOR_DRAW_DELAY 3
-
- #define CURSOR_UNDRAWN() \
- do { \
- del_timer( &atacon_cursor_timer ); \
- cursor_drawn = 0; \
- } while(0)
-
- #endif
-
- #ifdef CURSOR_DELAY_VBL
-
- /* The VBL cursor looks much better than the timer cursor, because the
- * inverting is done only in the VBlank time, when nothing is
- * displayed. This avoids flickering when moving the cursor fastly. I
- * guess the timer cursor will go away in futuere.
- */
-
- /* Time to elapse before the cursor is really drawn, in VBL units
- * (60 Hz: 17 ms, 72 Hz: 14 ms)
- */
- #define CURSOR_DRAW_DELAY 2
-
- /* # VBL ints between cursor state changes */
- #define DEFAULT_CURSOR_BLINK_RATE 42
-
- static int vbl_cursor_cnt = 0;
- static int cursor_on = 0;
- static int cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-
- #define CURSOR_UNDRAWN() \
- do { \
- vbl_cursor_cnt = 0; \
- cursor_drawn = 0; \
- } while(0)
-
- #endif
-
-
- /***************************** Prototypes *****************************/
-
- static void detect_video( ushort *yres, ushort *xres, ushort *depth, ushort
- *shiftmode );
- static int shifter_init( u_long adr);
- static int atacon_init( struct condata *conp, long mem_start);
- static int atacon_deinit( struct condata *conp);
- static __inline__ void *mymemclear_small( void * s, size_t count);
- static __inline__ void *mymemclear( void * s, size_t count);
- static __inline__ void *mymemmove( void * d, void * s, size_t count);
- static __inline__ void memclear_4p_col( void *d, size_t h, u_long val,
- u_short bpr );
- static __inline__ void memset_even_4p( void *d, size_t count, u_long val1,
- u_long val2 );
- static __inline__ void memmove_4p_col( void *d, void *s, u_short h, u_short
- bpr );
- static __inline__ unsigned long expand4l( unsigned char c );
- static __inline__ void expand4dl( unsigned char c, unsigned long *ret1,
- unsigned long *ret2 );
- static __inline__ unsigned long dup4l( unsigned char c );
- static __inline__ void memclear_8p_col( void *d, size_t h, u_long val1,
- u_long val2, u_short bpr );
- static __inline__ void memset_even_8p( void *d, size_t count, u_long val1,
- u_long val2, u_long val3, u_long
- val4 );
- static __inline__ void memmove_8p_col( void *d, void *s, u_short h, u_short
- bpr );
- static __inline__ void expand8dl( unsigned char c, u_long *ret1, u_long
- *ret2 );
- static __inline__ void expand8ql( unsigned char c, unsigned long *ret1,
- unsigned long *ret2, unsigned long *ret3,
- unsigned long *ret4 );
- static __inline__ void memclear_2p_col( void *d, size_t h, u_short val,
- u_short bpr );
- static __inline__ void memset_even_2p( void *d, size_t count, u_long val );
- static __inline__ void memmove_2p_col( void *d, void *s, u_short h, u_short
- bpr );
- static __inline__ unsigned short expand2w( unsigned char c );
- static __inline__ unsigned short dup2w( unsigned char c );
- static int atacon_bmove( struct condata *conp, int sy, int sx, int dy, int
- dx, int height, int width);
- static int atacon_clear( struct condata *conp, int sy, int sx, int height,
- int width);
- static int atacon_putc( struct condata *conp, int c, int y, int x, int
- mode);
- static int atacon_putcs( struct condata *conp, const char *s, int count,
- int y, int x, int mode);
- static int atacon_scroll( struct condata *conp, int t, int b, int dir, int
- count);
- static int atacon_switch( struct condata *conp);
- static void atacon_bmove_1_plane( register struct display *p, int sy, int
- sx, int dy, int dx, int height, int
- width);
- static void atacon_clear_1_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width );
- static void atacon_putc_1_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode);
- static void atacon_putcs_1_plane( struct condata *conp, struct display *p,
- const char *s, int count, int y, int x,
- int mode);
- static void atacon_rev_char_1_plane( struct display *display, int x, int y
- );
- #ifdef CONFIG_ATARI_2PLANE
- static void atacon_bmove_2_plane( register struct display *p, int sy, int
- sx, int dy, int dx, int height, int
- width);
- static void atacon_clear_2_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width );
- static void atacon_putc_2_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode);
- static void atacon_putcs_2_plane( struct condata *conp, struct display *p,
- const char *s, int count, int y, int x,
- int mode);
- static void atacon_rev_char_2_plane( struct display *display, int x, int y
- );
- #endif
- #ifdef CONFIG_ATARI_4PLANE
- static void atacon_bmove_4_plane( register struct display *p, int sy, int
- sx, int dy, int dx, int height, int
- width);
- static void atacon_clear_4_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width );
- static void atacon_putc_4_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode);
- static void atacon_putcs_4_plane( struct condata *conp, struct display *p,
- const char *s, int count, int y, int x,
- int mode);
- static void atacon_rev_char_4_plane( struct display *display, int x, int y
- );
- #endif
- #ifdef CONFIG_ATARI_8PLANE
- static void atacon_bmove_8_plane( register struct display *p, int sy, int
- sx, int dy, int dx, int height, int
- width);
- static void atacon_clear_8_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width );
- static void atacon_putc_8_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode);
- static void atacon_putcs_8_plane( struct condata *conp, struct display *p,
- const char *s, int count, int y, int x,
- int mode);
- static void atacon_rev_char_8_plane( struct display *display, int x, int y
- );
- #endif
- #ifdef CURSOR_DELAY_TIMER
- static void atacon_curtimfunc( unsigned long _disp );
- #endif
- #ifdef CURSOR_DELAY_VBL
- static void atacon_vbl_handler( struct intframe *fp, void *dummy );
- #endif
- static int atacon_cursor( struct condata *conp, int mode);
-
- /************************* End of Prototypes **************************/
-
-
- struct display_switch
- dispsw_1_plane = {
- atacon_bmove_1_plane, atacon_clear_1_plane, atacon_putc_1_plane,
- atacon_putcs_1_plane, atacon_rev_char_1_plane
- }
- #ifdef CONFIG_ATARI_2PLANE
- , dispsw_2_plane = {
- atacon_bmove_2_plane, atacon_clear_2_plane, atacon_putc_2_plane,
- atacon_putcs_2_plane, atacon_rev_char_2_plane
- }
- #endif
- #ifdef CONFIG_ATARI_4PLANE
- , dispsw_4_plane = {
- atacon_bmove_4_plane, atacon_clear_4_plane, atacon_putc_4_plane,
- atacon_putcs_4_plane, atacon_rev_char_4_plane
- }
- #endif
- #ifdef CONFIG_ATARI_8PLANE
- , dispsw_8_plane = {
- atacon_bmove_8_plane, atacon_clear_8_plane, atacon_putc_8_plane,
- atacon_putcs_8_plane, atacon_rev_char_8_plane
- }
- #endif
- #ifdef CONFIG_ATARI_16PLANE
- , dispsw_16_plane = {
- atacon_bmove_16_plane, atacon_clear_16_plane, atacon_putc_16_plane,
- atacon_putcs_16_plane, atacon_rev_char_16_plane
- }
- #endif
- ;
-
-
-
-
- #ifdef CURSOR_DELAY_TIMER
-
- static struct timer_list atacon_cursor_timer = { NULL,0,0,atacon_curtimfunc };
-
- #endif
-
-
- /* ================================================================= */
- /* Initialization Functions */
- /* ================================================================= */
-
-
- /* atari_video_setup() processes command line options and stores them
- * in atacon_default_font and atacon_default_shiftmode. Their validity
- * is checked later.
- */
-
- void atari_video_setup( char *options, int *ints )
-
- { char *this_opt;
- int i, max;
-
- if (!options || !*options)
- return;
-
- for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
-
- if (!*this_opt) continue;
-
- if (!strcmp (this_opt, "f8x8")) {
- atacon_default_font = 8;
- }
- else if (!strcmp (this_opt, "f8x16")) {
- atacon_default_font = 16;
- }
- else {
-
- if (boot_info.bi_atari.model == ATARI_TT) {
- max = sizeof(tt_video_modes)/sizeof(tt_video_modes[0]);
- for (i = 0; i < max; i++) {
- if (!strcmp( this_opt, tt_video_modes[i].name )) {
- atacon_default_shiftmode = i;
- break;
- }
- }
- }
- else {
- max = sizeof(falcon_video_modes)/sizeof(falcon_video_modes[0]);
- for (i = 0; i < max; i++) {
- if (!strcmp( this_opt, falcon_video_modes[i].name )) {
- atacon_default_shiftmode = i;
- break;
- }
- }
- }
-
- if (i == max)
- printk( "atari_video_setup: Unknown option %s\n", this_opt );
- }
- }
- }
-
-
- /* detect_video() selects a screen size/depth pair and programs the
- * hardware for this mode. It chooses the shift mode given on the
- * command line, if this is possible with the connected monitor type.
- * Else is falls back to a default mode for the monitor.
- * Note that this isn't implemented for the Falcon yet, because there
- * are many, many possibilities. The Falcon uses always St High mode
- * for now. To be re-worked.
- */
-
- static void detect_video( ushort *yres, ushort *xres, ushort *depth,
- ushort *shiftmode )
-
- { static int detected = 0;
-
- if (boot_info.bi_atari.model == ATARI_TT) {
-
- int mono_moni, i;
-
- if (!detected) {
- /* Determine the connected monitor: The DMA sound must be
- * disabled before reading the MFP GPIP, because the Sound
- * Done Signal and the Monochrome Detect are XORed together!
- */
-
- tt_dmasnd.ctrl = DMASND_CTRL_OFF;
- udelay( 20 ); /* wait a while for things to settle down */
- mono_moni = (mfp.par_dt_reg & 0x80) == 0;
-
- /* If the command line shift mode isn't compatible with the
- * monitor type, reset it to -1. A default mode will be
- * selected then below.
- */
-
- if (atacon_default_shiftmode != -1)
- if ((mono_moni && atacon_default_shiftmode != TT_HIGH) ||
- (!mono_moni && atacon_default_shiftmode == TT_HIGH))
- atacon_default_shiftmode = -1;
-
- /* Set a default shift mode, if none was given on the command
- * line or that isn't possible.
- */
- if (atacon_default_shiftmode == -1)
- atacon_default_shiftmode = mono_moni ? TT_HIGH :
- #ifdef CONFIG_ATARI_4PLANE
- ST_HIGH;
- #else
- TT_MID;
- #endif
-
- /* Initialize the shift mode, palette bank = 0 */
- shifter_tt.tt_shiftmode = atacon_default_shiftmode << 8;
-
- /* Set up the colormap registers */
- if (tt_video_modes[atacon_default_shiftmode].depth >= 4) {
- for( i = 0; i < 16; ++i )
- tt_palette[i] = default_16_colors[i];
- }
- else if (tt_video_modes[atacon_default_shiftmode].depth == 2) {
- for( i = 0; i < 4; ++i )
- tt_palette[i] = default_4_colors[i];
- }
- else /* depth == 1 */ {
- tt_palette[254] = 0x000; /* black */
- tt_palette[255] = 0xfff; /* white */
- }
-
- detected = 1;
- }
-
- *yres = tt_video_modes[atacon_default_shiftmode].yres;
- *xres = tt_video_modes[atacon_default_shiftmode].xres;
- *depth = tt_video_modes[atacon_default_shiftmode].depth;
- *shiftmode = atacon_default_shiftmode;
- }
- else if (boot_info.bi_atari.model == ATARI_FALCON) {
-
- *yres = 400;
- *xres = 640;
- *depth = 1;
-
- }
- }
-
- static int shifter_init(u_long adr)
- {
- /* Setup Screen Memory */
- shifter.bas_hi=(u_char)((adr & 0xff0000) >> 16);
- shifter.bas_md=(u_char)((adr & 0x00ff00) >> 8);
- shifter.bas_lo=(u_char)(adr & 0x0000ff);
- return 0;
- }
-
-
- static int atacon_init(struct condata *conp, long mem_start)
- {
- int unit = conp - vc_cons;
-
- /* set up the display defaults */
- detect_video( &disp[unit].scr_height, &disp[unit].scr_width,
- &disp[unit].scr_depth, &disp[unit].shiftmode );
-
- /* If no font was selected on the command line, choose a default
- * font: This is 8x8 if the display has less than 400 lines, 8x16
- * else.
- */
- if (atacon_default_font == -1)
- atacon_default_font = (disp[unit].scr_height < 400) ? 8 : 16;
-
- if (atacon_default_font == 16) {
- disp[unit].fontdata = fontdata_8x16;
- disp[unit].fontheight = fontheight_8x16;
- disp[unit].fontwidth = fontwidth_8x16;
- }
- else if (atacon_default_font == 8) {
- disp[unit].fontdata = fontdata_8x8;
- disp[unit].fontheight = fontheight_8x8;
- disp[unit].fontwidth = fontwidth_8x8;
- }
- else
- panic( "atacon_init: No support for fontheight %d.\n",
- atacon_default_font );
-
- disp[unit].bytes_per_row = (disp[unit].scr_width >> 3) *
- disp[unit].scr_depth;
- disp[unit].cursor_x = 0;
- disp[unit].cursor_y = 0;
-
- if (disp[unit].scr_depth == 1) {
- disp[unit].dispsw = &dispsw_1_plane;
- disp[unit].fgcol = 1;
- disp[unit].bgcol = 0;
- }
- #ifdef CONFIG_ATARI_2PLANE
- else if (disp[unit].scr_depth == 2) {
- disp[unit].dispsw = &dispsw_2_plane;
- disp[unit].fgcol = 3;
- disp[unit].bgcol = 0;
- }
- #endif
- #ifdef CONFIG_ATARI_4PLANE
- else if (disp[unit].scr_depth == 4) {
- disp[unit].dispsw = &dispsw_4_plane;
- disp[unit].fgcol = 7;
- disp[unit].bgcol = 0;
- }
- #endif
- #ifdef CONFIG_ATARI_8PLANE
- else if (disp[unit].scr_depth == 8) {
- disp[unit].dispsw = &dispsw_8_plane;
- disp[unit].fgcol = 7;
- disp[unit].bgcol = 0;
- }
- #endif
- #ifdef CONFIG_ATARI_16PLANE
- else if (disp[unit].scr_depth == 16) {
- disp[unit].dispsw = &dispsw_16_plane;
- disp[unit].fgcol = 0xbbbbbb;
- disp[unit].bgcol = 0;
- }
- #endif
- else
- panic( "atacon_init: %d planes not supported.\n",
- disp[unit].scr_depth );
-
- conp->vc_cols = disp[unit].scr_width / disp[unit].fontwidth;
- conp->vc_rows = disp[unit].scr_height / disp[unit].fontheight;
-
- mem_req = (disp[unit].scr_width/8)*disp[unit].scr_height*
- disp[unit].scr_depth;
- /* locate the bitplane */
- mem_start = (mem_start + 7) & ~7; /* round up */
- disp[unit].bitplane = (u_char *)mem_start;
- mem_start += mem_req;
- mymemclear( disp[unit].bitplane, mem_req );
-
- shifter_init( (u_long)(disp[unit].bitplane) );
-
-
- #ifdef CURSOR_DELAY_VBL
- add_isr( IRQ4, atacon_vbl_handler, 0, NULL );
- #endif
-
- return mem_start;
- }
-
- static int atacon_deinit (struct condata *conp)
- {
- return 0;
- }
-
-
- /* ================================================================= */
- /* Utility Assembler Functions */
- /* ================================================================= */
-
-
- /* ====================================================================== */
-
- /* Those of a delicate disposition might like to skip the next couple of
- * pages.
- *
- * These functions are drop in replacements for memmove and
- * memset(_, 0, _). However their five instances add at least a kilobyte
- * to the object file. You have been warned.
- *
- * Not a great fan of assembler for the sake of it, but I think
- * that these routines are at least 10 times faster than their C
- * equivalents for large blits, and thats important to the lowest level of
- * a graphics driver. Question is whether some scheme with the blitter
- * would be faster. I suspect not for simple text system - not much
- * asynchronisity.
- *
- * Code is very simple, just gruesome expansion. Basic strategy is to
- * increase data moved/cleared at each step to 16 bytes to reduce
- * instruction per data move overhead. movem might be faster still
- * For more than 15 bytes, we try to align the write direction on a
- * longword boundary to get maximum speed. This is even more gruesome.
- * Unaligned read/write used requires 68020+ - think this is a problem?
- *
- * Sorry!
- */
-
- /* ++roman: I've optimized Robert's original versions in some minor
- * aspects, e.g. moveq instead of movel, let gcc choose the registers,
- * use movem in some places...
- * For other modes than 1 plane, lots of more such assembler functions
- * were needed (e.g. the ones using movep or expanding color values).
- */
-
-
- static __inline__ void *mymemclear_small(void * s, size_t count)
- {
- long tmp1, tmp2, tmp3, tmp4;
-
- if (!count) return(0);
-
- __asm__ __volatile__
- ("moveq #0,%2 ; movel %2,%3 ; movel %2,%4 ; movel %2,%5\n\t"
- "addl %1,%0\n\t"
- "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
- "1: subql #1,%1 ; jcs 3f\n\t"
- "2: moveml %2/%3/%4/%5,%0@-\n\t"
- "dbra %1,2b\n\t"
- "3:"
- : "=a" (s), "=d" (count), "=d" (tmp1), "=d" (tmp2), "=d" (tmp3), "=d" (tmp4)
- : "0" (s), "1" (count)
- );
-
- return(0);
- }
-
- static __inline__ void *mymemclear(void * s, size_t count)
- {
- if (!count)
- return(0);
-
- else if (count < 16) {
- long tmp;
- __asm__ __volatile__
- ("moveq #0,%2\n\t"
- "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@+\n\t"
- "1:lsrl #1,%1 ; jcc 1f ; movew %2,%0@+\n\t"
- "1:lsrl #1,%1 ; jcc 1f ; movel %2,%0@+\n\t"
- "1:lsrl #1,%1 ; jcc 1f ; movel %2,%0@+ ; movel %2,%0@+\n\t"
- "1:"
- : "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (s), "1" (count)
- );
- }
-
- else {
- long tmp;
- __asm__ __volatile__
- ("movel %1,%2\n\t"
- "lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
- "lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t"
- "1: lsrl #1,%2 ; jcc 2f\n\t"
- "clrw %0@+ ; subqw #2,%1\n\t"
- "2: movew %1,sp@-; moveq #0,%2 ; lsrl #2,%1 ; jeq 6f\n\t"
- "lsrl #1,%1 ; jcc 3f ; movel %2,%0@+\n\t"
- "3: lsrl #1,%1 ; jcc 4f ; movel %2,%0@+ ; movel %2,%0@+\n\t"
- "4: subql #1,%1 ; jcs 6f\n\t"
- "5: movel %2,%0@+; movel %2,%0@+ ; movel %2,%0@+ ; movel %2,%0@+\n\t"
- "dbra %1,5b ; subl #65536,%1; jcc 5b\n\t"
- "6: movew sp@+,%1; btst #1,%1 ; jeq 7f ; movew %2,%0@+\n\t"
- "7: ; btst #0,%1 ; jeq 8f ; moveb %2,%0@+\n\t"
- "8:"
- : "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (s), "1" (count)
- );
- }
-
- return(0);
- }
-
- static __inline__ void *mymemmove(void * d, void * s, size_t count)
- {
- if (d < s) {
- if (count < 16) {
- __asm__ __volatile__
- ("lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" (d), "1" (s), "2" (count)
- );
- } else {
- long tmp;
- __asm__ __volatile__
- ("movel %0,%3\n\t"
- "lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
- "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
- "1: lsrl #1,%3 ; jcc 2f\n\t"
- "movew %1@+,%0@+ ; subqw #2,%2\n\t"
- "2: movew %2,sp@-; lsrl #2,%2 ; jeq 6f\n\t"
- "lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
- "3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
- "4: subql #1,%2 ; jcs 6f\n\t"
- "5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+;movel %1@+,%0@+\n\t"
- "dbra %2,5b ; subl #65536,%2; jcc 5b\n\t"
- "6: movew sp@+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
- "7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (d), "1" (s), "2" (count)
- );
- }
- } else {
- if (count < 16) {
- __asm__ __volatile__
- ("addal %2,%0 ; addal %2,%1\n\t"
- "lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
- "1:lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" (d), "1" (s), "2" (count)
- );
- } else {
- long tmp;
- __asm__ __volatile__
- ("addal %2,%0 ; addal %2,%1; movel %0,%3\n\t"
- "lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
- "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
- "1: lsrl #1,%3 ; jcc 2f\n\t"
- "movew %1@-,%0@- ; subqw #2,%2\n\t"
- "2: movew %2,sp@-; lsrl #2,%2 ; jeq 6f\n\t"
- "lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
- "3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
- "4: subql #1,%2 ; jcs 6f\n\t"
- "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
- "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
- "dbra %2,5b ; subl #65536,%2; jcc 5b\n\t"
- "6: movew sp@+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
- "7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (d), "1" (s), "2" (count)
- );
- }
- }
- return(0);
- }
-
- /* Sets the bytes in the visible column at d, height h, to the value
- * val for a 4 plane screen. The the bis of the color in 'color' are
- * moved (8 times) to the respective bytes. This means:
- *
- * for( h times; d += bpr )
- * *d = (color & 1) ? 0xff : 0;
- * *(d+2) = (color & 2) ? 0xff : 0;
- * *(d+4) = (color & 4) ? 0xff : 0;
- * *(d+6) = (color & 8) ? 0xff : 0;
- */
-
- static __inline__ void memclear_4p_col( void *d, size_t h,
- u_long val, u_short bpr )
-
- {
- __asm__ __volatile__
- ( "subql #1,%1\n\t"
- "1: movepl %4,%0@(0)\n\t"
- "addaw %5,%0\n\t"
- "dbra %1,1b"
- : "=a" (d), "=d" (h)
- : "0" (d), "1" (h), "d" (val), "r" (bpr)
- );
- }
-
- /* Sets a 4 plane region from 'd', length 'count' bytes, to the color
- * in val1/val2. 'd' has to be an even address and count must be divisible
- * by 8, because only whole words and all planes are accessed. I.e.:
- *
- * for( count/8 times )
- * *d = *(d+1) = (color & 1) ? 0xff : 0;
- * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
- * *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
- * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
- */
-
- static __inline__ void memset_even_4p( void *d, size_t count,
- u_long val1, u_long val2 )
-
- {
- __asm__ __volatile__
- ( "lsrl #3,%1\n\t"
- "subql #1,%1\n\t"
- "1: movel %4,%0@+\n\t"
- "movel %5,%0@+\n\t"
- "dbra %1,1b\n\t"
- "subl #65536,%1\n\t"
- "jcc 1b"
- : "=a" (d), "=d" (count)
- : "0" (d), "1" (count), "d" (val1), "d" (val2)
- );
- }
-
- /* Copies a 4 plane column from 's', height 'h', to 's'. */
-
- static __inline__ void memmove_4p_col( void *d, void *s, u_short h,
- u_short bpr )
-
- { unsigned long tmp;
-
- __asm__ __volatile__
- ( "subqw #1,%2\n\t"
- "1: movepl %0@(0),%3\n\t"
- "movepl %3,%1@(0)\n\t"
- "addaw %7,%0\n\t"
- "addaw %7,%1\n\t"
- "dbra %2,1b"
- : "=a" (s), "=a" (d), "=d" (h), "=&d" (tmp)
- : "0" (s), "1" (d), "2" (h), "d" (bpr)
- );
- }
-
-
- /* This expands a 4 bit color into a long for movepl (4 plane) operations. */
-
- static __inline__ unsigned long expand4l( unsigned char c )
-
- { unsigned long rv;
-
- __asm__ __volatile__
- ( "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%2\n\t"
- "scs %0\n\t"
- : "=&d" (rv), "=d" (c)
- : "1" (c)
- );
- return( rv );
- }
-
- /* This expands a 4 bit color into two longs for two movel operations
- * (4 planes).
- */
-
- static __inline__ void expand4dl( unsigned char c, unsigned long *ret1,
- unsigned long *ret2 )
-
- { unsigned long rv1, rv2;
-
- __asm__ __volatile__
- ( "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- "swap %0\n\t"
- "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- "lsrb #1,%3\n\t"
- "scs %1\n\t"
- "extw %1\n\t"
- "swap %1\n\t"
- "lsrb #1,%3\n\t"
- "scs %1\n\t"
- "extw %1"
- : "=&d" (rv1), "=&d" (rv2), "=d" (c)
- : "2" (c)
- );
- *ret1 = rv1;
- *ret2 = rv2;
- }
-
-
- /* This duplicates a byte 4 times into a long. */
-
- static __inline__ unsigned long dup4l( unsigned char c )
-
- { ushort tmp;
- ulong rv;
-
- __asm__ __volatile__
- ( "moveb %2,%0\n\t"
- "lslw #8,%0\n\t"
- "moveb %2,%0\n\t"
- "movew %0,%1\n\t"
- "swap %0\n\t"
- "movew %1,%0"
- : "=&d" (rv), "=d" (tmp)
- : "d" (c)
- );
-
- return( rv );
- }
-
-
- /* Sets the bytes in the visible column at d, height h, to the value
- * val1,val2 for a 8 plane screen. The the bis of the color in 'color' are
- * moved (8 times) to the respective bytes. This means:
- *
- * for( h times; d += bpr )
- * *d = (color & 1) ? 0xff : 0;
- * *(d+2) = (color & 2) ? 0xff : 0;
- * *(d+4) = (color & 4) ? 0xff : 0;
- * *(d+6) = (color & 8) ? 0xff : 0;
- * *(d+8) = (color & 16) ? 0xff : 0;
- * *(d+10) = (color & 32) ? 0xff : 0;
- * *(d+12) = (color & 64) ? 0xff : 0;
- * *(d+14) = (color & 128) ? 0xff : 0;
- */
-
- static __inline__ void memclear_8p_col( void *d, size_t h, u_long val1,
- u_long val2, u_short bpr )
-
- {
- __asm__ __volatile__
- ( "subql #1,%1\n\t"
- "1: movepl %4,%0@(0)\n\t"
- "movepl %5,%0@(8)\n\t"
- "addaw %6,%0\n\t"
- "dbra %1,1b"
- : "=a" (d), "=d" (h)
- : "0" (d), "1" (h), "d" (val1), "d" (val2), "r" (bpr)
- );
- }
-
- /* Sets a 8 plane region from 'd', length 'count' bytes, to the color
- * val1..val4. 'd' has to be an even address and count must be divisible
- * by 16, because only whole words and all planes are accessed. I.e.:
- *
- * for( count/16 times )
- * *d = *(d+1) = (color & 1) ? 0xff : 0;
- * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
- * *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
- * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
- * *(d+8) = *(d+9) = (color & 16) ? 0xff : 0;
- * *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
- * *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
- * *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
- */
-
- static __inline__ void memset_even_8p( void *d, size_t count,
- u_long val1, u_long val2,
- u_long val3, u_long val4 )
-
- {
- __asm__ __volatile__
- ( "lsrl #4,%1\n\t"
- "subql #1,%1\n\t"
- "1: movel %4,%0@+\n\t"
- "movel %5,%0@+\n\t"
- "movel %6,%0@+\n\t"
- "movel %7,%0@+\n\t"
- "dbra %1,1b\n\t"
- "subl #65536,%1\n\t"
- "jcc 1b"
- : "=a" (d), "=d" (count)
- : "0" (d), "1" (count), "d" (val1), "d" (val2),
- "d" (val3), "d" (val4)
- );
- }
-
- /* Copies a 8 plane column from 's', height 'h', to 's'. */
-
- static __inline__ void memmove_8p_col( void *d, void *s, u_short h,
- u_short bpr )
-
- { unsigned long tmp;
-
- __asm__ __volatile__
- ( "subqw #1,%2\n\t"
- "1: movepl %0@(0),%3\n\t"
- "movepl %3,%1@(0)\n\t"
- "movepl %0@(8),%3\n\t"
- "movepl %3,%1@(8)\n\t"
- "addaw %7,%0\n\t"
- "addaw %7,%1\n\t"
- "dbra %2,1b"
- : "=a" (s), "=a" (d), "=d" (h), "=&d" (tmp)
- : "0" (s), "1" (d), "2" (h), "d" (bpr)
- );
- }
-
-
- /* This expands a 8 bit color into two longs for two movepl (8 plane)
- * operations.
- */
-
- static __inline__ void expand8dl( unsigned char c, u_long *ret1,
- u_long *ret2 )
-
- { unsigned long rv1, rv2;
-
- __asm__ __volatile__
- ( "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%3\n\t"
- "scs %0\n\t"
- "lsrb #1,%3\n\t"
- "scs %1\n\t"
- "lsll #8,%1\n\t"
- "lsrb #1,%3\n\t"
- "scs %1\n\t"
- "lsll #8,%1\n\t"
- "lsrb #1,%3\n\t"
- "scs %1\n\t"
- "lsll #8,%1\n\t"
- "lsrb #1,%3\n\t"
- "scs %1"
- : "=&d" (rv1), "=&d" (rv2),"=d" (c)
- : "2" (c)
- );
-
- *ret1 = rv1;
- *ret2 = rv2;
- }
-
- /* This expands a 8 bit color into four longs for four movel operations
- * (8 planes).
- */
-
- static __inline__ void expand8ql( unsigned char c, unsigned long *ret1,
- unsigned long *ret2, unsigned long
- *ret3, unsigned long *ret4 )
-
- { unsigned long rv1, rv2, rv3, rv4;
-
- __asm__ __volatile__
- ( "lsrb #1,%5\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- "swap %0\n\t"
- "lsrb #1,%5\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- "lsrb #1,%5\n\t"
- "scs %1\n\t"
- "extw %1\n\t"
- "swap %1\n\t"
- "lsrb #1,%5\n\t"
- "scs %1\n\t"
- "extw %1\n\t"
- "lsrb #1,%5\n\t"
- "scs %2\n\t"
- "extw %2\n\t"
- "swap %2\n\t"
- "lsrb #1,%5\n\t"
- "scs %2\n\t"
- "extw %2\n\t"
- "lsrb #1,%5\n\t"
- "scs %3\n\t"
- "extw %3\n\t"
- "swap %3\n\t"
- "lsrb #1,%5\n\t"
- "scs %3\n\t"
- "extw %3"
- : "=&d" (rv1), "=&d" (rv2), "=&d" (rv3), "=&d" (rv4), "=d" (c)
- : "4" (c)
- );
-
- *ret1 = rv1;
- *ret2 = rv2;
- *ret3 = rv3;
- *ret4 = rv4;
- }
-
-
-
- /* Sets the bytes in the visible column at d, height h, to the value
- * val for a 2 plane screen. The the bis of the color in 'color' are
- * moved (8 times) to the respective bytes. This means:
- *
- * for( h times; d += bpr )
- * *d = (color & 1) ? 0xff : 0;
- * *(d+2) = (color & 2) ? 0xff : 0;
- */
-
- static __inline__ void memclear_2p_col( void *d, size_t h,
- u_short val, u_short bpr )
-
- {
- __asm__ __volatile__
- ( "subql #1,%1\n\t"
- "1: movepw %4,%0@(0)\n\t"
- "addaw %5,%0\n\t"
- "dbra %1,1b"
- : "=a" (d), "=d" (h)
- : "0" (d), "1" (h), "d" (val), "r" (bpr)
- );
- }
-
- /* Sets a 2 plane region from 'd', length 'count' bytes, to the color
- * in val1. 'd' has to be an even address and count must be divisible
- * by 8, because only whole words and all planes are accessed. I.e.:
- *
- * for( count/4 times )
- * *d = *(d+1) = (color & 1) ? 0xff : 0;
- * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
- */
-
- static __inline__ void memset_even_2p( void *d, size_t count, u_long val )
-
- {
- __asm__ __volatile__
- ( "lsrl #2,%1\n\t"
- "subql #1,%1\n\t"
- "1: movel %4,%0@+\n\t"
- "dbra %1,1b\n\t"
- "subl #65536,%1\n\t"
- "jcc 1b"
- : "=a" (d), "=d" (count)
- : "0" (d), "1" (count), "d" (val)
- );
- }
-
- /* Copies a 2 plane column from 's', height 'h', to 's'. */
-
- static __inline__ void memmove_2p_col( void *d, void *s, u_short h,
- u_short bpr )
-
- { unsigned short tmp;
-
- __asm__ __volatile__
- ( "subqw #1,%2\n\t"
- "1: movepw %0@(0),%3\n\t"
- "movepw %3,%1@(0)\n\t"
- "addaw %7,%0\n\t"
- "addaw %7,%1\n\t"
- "dbra %2,1b"
- : "=a" (s), "=a" (d), "=d" (h), "=&d" (tmp)
- : "0" (s), "1" (d), "2" (h), "d" (bpr)
- );
- }
-
-
- /* This expands a 2 bit color into a short for movepw (2 plane) operations. */
-
- static __inline__ unsigned short expand2w( unsigned char c )
-
- { unsigned short rv;
-
- __asm__ __volatile__
- ( "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "lsll #8,%0\n\t"
- "lsrb #1,%2\n\t"
- "scs %0\n\t"
- : "=&d" (rv), "=d" (c)
- : "1" (c)
- );
- return( rv );
- }
-
- /* This expands a 2 bit color into one long for a movel operation
- * (2 planes).
- */
-
- static __inline__ void expand2l( unsigned char c, unsigned long *ret )
-
- { unsigned long rv;
-
- __asm__ __volatile__
- ( "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- "swap %0\n\t"
- "lsrb #1,%2\n\t"
- "scs %0\n\t"
- "extw %0\n\t"
- : "=&d" (rv), "=d" (c)
- : "1" (c)
- );
-
- *ret = rv;
- }
-
-
- /* This duplicates a byte 2 times into a short. */
-
- static __inline__ unsigned short dup2w( unsigned char c )
-
- { ushort rv;
-
- __asm__ __volatile__
- ( "moveb %1,%0\n\t"
- "lslw #8,%0\n\t"
- "moveb %1,%0\n\t"
- : "=&d" (rv)
- : "d" (c)
- );
-
- return( rv );
- }
-
-
-
- /* ====================================================================== */
-
- /* atacon_XXX routines - interface used by the world
- *
- * This system is now divided into two levels because of complications
- * caused by hardware scrolling. Top level functions:
- *
- * atacon_bmove(), atacon_clear(), atacon_putc()
- *
- * handles y values in range [0, scr_height-1] that correspond to real
- * screen positions.
- *
- * atacon_bmove_physical_8() -- These functions fast implementations
- * atacon_clear_physical_8() -- of original atacon_XXX fns.
- * atacon_putc_physical_8() -- (fontwidth != 8) may be added later
- *
- */
-
-
- static int atacon_bmove (struct condata *conp,
- int sy, int sx, int dy, int dx,
- int height, int width)
- {
- int unit = conp - vc_cons;
- struct display *p = &disp[unit];
-
- if ((sy <= p->cursor_y && p->cursor_y < sy+height &&
- sx <= p->cursor_x && p->cursor_x < sx+width) ||
- (dy <= p->cursor_y && p->cursor_y < dy+height &&
- dx <= p->cursor_x && p->cursor_x < dx+width))
- atacon_cursor( conp, CM_ERASE );
-
- p->dispsw->bmove( p, sy, sx, dy, dx, height, width );
- return(0);
- }
-
- static int atacon_clear (struct condata *conp,
- int sy, int sx, int height, int width)
- {
- int unit = conp - vc_cons;
- register struct display *p = &disp[unit];
-
- if (sy <= p->cursor_y && p->cursor_y < sy+height &&
- sx <= p->cursor_x && p->cursor_x < sx+width)
- CURSOR_UNDRAWN();
-
- p->dispsw->clear( conp, p, sy, sx, height, width );
-
- return(0);
- }
-
- static int atacon_putc (struct condata *conp,
- int c, int y, int x, int mode)
- {
- int unit = conp - vc_cons;
- register struct display *p = &disp[unit];
-
- if (p->cursor_x == x && p->cursor_y == y)
- CURSOR_UNDRAWN();
-
- p->dispsw->putc( conp, p, c, y, x, mode );
-
- return(0);
- }
-
- static int atacon_putcs (struct condata *conp, const char *s,
- int count, int y, int x, int mode)
- {
- int unit = conp - vc_cons;
- register struct display *p = &disp[unit];
-
- if (p->cursor_y == y &&
- x <= p->cursor_x && p->cursor_x < x+count)
- CURSOR_UNDRAWN();
-
- p->dispsw->putcs( conp, p, s, count, y, x, mode );
-
- return(0);
- }
-
-
- static int atacon_scroll (struct condata *conp,
- int t, int b, int dir, int count)
- {
- switch (dir) {
-
- case SM_UP:
- atacon_bmove( conp, t + count, 0, t, 0,
- (b-t-count), conp->vc_cols );
- atacon_clear( conp, b-count, 0, count, conp->vc_cols );
- break;
-
- case SM_DOWN:
- atacon_bmove( conp, t, 0, t+count, 0,
- (b-t-count), conp->vc_cols );
-
- /* Fixed bmove() should end Arno's frustration with copying?
- * Confusius say:
- * Man who copies in wrong direction, end up with trashed data
- */
-
- atacon_clear( conp, t, 0, count, conp->vc_cols );
- break;
-
- case SM_LEFT:
- atacon_bmove( conp, 0, t + count, 0, t,
- conp->vc_rows, (b-t-count) );
- atacon_clear( conp, 0, b-count, conp->vc_rows, count );
- break;
-
- case SM_RIGHT:
- atacon_bmove( conp, 0, t, 0, t+count,
- conp->vc_rows, (b-t-count) );
- atacon_clear( conp, 0, t, conp->vc_rows, count );
- break;
- }
-
- return 0;
- }
-
- static int atacon_switch (struct condata *conp)
- {
- return 0;
- }
-
-
-
- /* ================================================================= */
- /* 1 Plane Functions */
- /* ================================================================= */
-
-
- static void atacon_bmove_1_plane( register struct display *p,
- int sy, int sx, int dy, int dx,
- int height, int width)
- {
-
- if (sx == 0 && dx == 0 && width == p->bytes_per_row) {
- mymemmove(p->bitplane + dy * width * p->fontheight,
- p->bitplane + sy * width * p->fontheight,
- width * height * p->fontheight );
- } else {
- register ushort rows;
- register u_char *src;
- register u_char *dst;
- register ushort bytes = p->bytes_per_row;
- register ushort linesize = bytes * p->fontheight;
-
- if (dy < sy || (dy == sy && dx < sx)) {
- src = p->bitplane + sy * linesize + sx;
- dst = p->bitplane + dy * linesize + dx;
- for (rows = height*p->fontheight ; rows-- ;) {
- mymemmove(dst, src, width);
- src += bytes;
- dst += bytes;
- }
- } else {
- src = p->bitplane + (sy+height) * linesize + sx - bytes;
- dst = p->bitplane + (dy+height) * linesize + dx - bytes;
-
- for (rows = height*p->fontheight ; rows-- ;) {
- mymemmove(dst, src, width);
- src -= bytes;
- dst -= bytes;
- }
- }
- }
- }
-
-
- static void atacon_clear_1_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width )
- {
- ulong offset;
- register u_char *start;
- register ushort rows;
- register ushort bytes = p->bytes_per_row;
- register ulong size;
-
- if (sx == 0 && width == bytes) {
- offset = sy * bytes * p->fontheight;
- size = height * bytes * p->fontheight;
- mymemclear( p->bitplane+offset, size );
- } else {
- offset = (sy * bytes * p->fontheight) + sx;
- start = p->bitplane+offset;
-
- for (rows = height*p->fontheight; rows-- ; start += bytes)
- mymemclear_small(start, width);
- }
- }
-
-
- static void atacon_putc_1_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode)
- {
- register u_char *dest;
- register u_char *cdat;
- register ushort rows;
- u_short bytes;
- ulong offset;
-
- if (!FONT_CNV(c)) return;
-
- bytes = p->bytes_per_row;
- offset = y * p->fontheight * bytes + x;
- dest = p->bitplane + offset;
- cdat = p->fontdata + (c * p->fontheight);
-
- if (conp->vc_intensity != 1 || conp->vc_reverse ^ conp->vc_decscnm) {
- register u_char andmask, xormask, c;
- register int bold;
-
- andmask = (conp->vc_intensity == 0) ? 0x55 : 0xff;
- xormask = (conp->vc_reverse ^ conp->vc_decscnm) ? 0xff : 0;
- bold = (conp->vc_intensity == 2);
-
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
- c = *cdat++;
- if (rows == 0 && conp->vc_underline) c = 0xff;
- c = (c & andmask) ^ xormask;
- if (bold) c |= c >> 1;
- *dest = c;
- }
- }
- else {
-
- for (rows = p->fontheight ; rows-- ; dest += bytes)
- *dest = *cdat++;
-
- if (conp->vc_underline)
- dest[-bytes] ^= ~0;
- }
- }
-
-
- static void atacon_putcs_1_plane( struct condata *conp, struct
- display *p, const char *s,
- int count, int y, int x, int mode)
- {
- register u_char *dest, *cdat;
- register ushort rows, bytes;
- register u_char c;
- u_char *dest0;
- ulong offset;
- int effects = (conp->vc_underline || conp->vc_intensity != 1 ||
- (conp->vc_reverse ^ conp->vc_decscnm));
-
- if (!count) return;
-
- bytes = p->bytes_per_row;
- offset = y * p->fontheight * bytes + x;
- dest0 = p->bitplane + offset;
-
- #if defined (__GNUC__) && defined (__mc68000__)
- if (!effects && p->fontheight == 8) {
- void *tmpa;
- /* Ultra special support for 8x8 fonts, as its nice and easy
- * and the console driver seems to spend most of its time in
- * here. Would take another 4 instructions to support,
- * (fontheight != 8) but I have an inbuilt suspicion of mulu's.
- * A hangover from my 68000 days, I guess.
- *
- * Both code and register use mirrors the C code directly below:
- *
- * a0 -- dest & dest0 [uses stack]
- * a1 -- cdat ; a2 -- s ; a3 -- fontdata
- * d0 -- scratch ; d1 -- count ; d2 -- bytes
- *
- */
- __asm__ __volatile__
- ("subqw #1,%1\n\t"
- "moveq #0,d0\n\t"
- "1: moveb %2@+,d0\n\t"
- #ifndef WHOLE_FONT
- "cmpb #32,d0 ; jlt 2f ; cmpb #127,d0 ; jge 2f\n\t"
- "subb #32,d0 ; jra 3f\n\t"
- "2: cmpb #160,d0 ; jlt 1b ; cmpb #255,d0 ; jeq 1b\n\t"
- "subb #64,d0\n\t3: "
- #else
- "moveb %9@(d0:w),d0 ; beq 1b\n\t"
- #endif
- "lea %7@(d0:w:8),%3 ; movel %0,sp@-\n\t"
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 0 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 1 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 2 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 3 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 4 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 5 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 6 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 7 */
- "movel sp@+,%0 ; addql #1,%0 ; dbra %1,1b\n\t"
- : "=a" (dest0), "=d" (count), "=a" (s), "=&a" (tmpa)
- : "0" (dest0), "1" (count), "2" (s), "a" (p->fontdata),
- "d" (bytes)
- #ifdef WHOLE_FONT
- , "a" (conp->vc_translate)
- #endif
- : "d0" /* Sorry, it isn't possible to let gcc choose
- * this register, too, because this would
- * require another output operand and thus give
- * more than 10 parameters total. But gcc can
- * only handle up to 10 parameters at present :-(
- */
- );
- return;
- }
- if (!effects && p->fontheight == 16) {
- /* ++roman: the same for 8x16 */
- void *tmpa;
- __asm__ __volatile__
- ("subqw #1,%1\n\t"
- "1: moveq #0,d0 ; moveb %2@+,d0\n\t"
- #ifndef WHOLE_FONT
- "cmpb #32,d0 ; jlt 2f ; cmpb #127,d0 ; jge 2f\n\t"
- "subb #32,d0 ; jra 3f\n\t"
- "2: cmpb #160,d0 ; jlt 1b ; cmpb #255,d0 ; jeq 1b\n\t"
- "subb #64,d0\n\t3: "
- #else
- "moveb %9@(d0:w),d0 ; beq 1b\n\t"
- #endif
- "lslw #4,d0 ; lea %7@(d0:w),%3 ; movel %0,sp@-\n\t"
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 0 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 1 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 2 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 3 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 4 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 5 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 6 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 7 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 8 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 9 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 10 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 11 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 12 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 13 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 14 */
- " moveb %3@+,%0@; addaw %8,%0\n\t" /* 15 */
- "movel sp@+,%0 ; addql #1,%0 ; dbra %1,1b\n\t"
- : "=a" (dest0), "=d" (count), "=a" (s), "=&a" (tmpa)
- : "0" (dest0), "1" (count), "2" (s), "a" (p->fontdata),
- "d" (bytes)
- #ifdef WHOLE_FONT
- , "a" (conp->vc_translate)
- #endif
- : "d0" /* Sorry, it isn't possible to let gcc choose
- * this register, too, because this would
- * require another output operand and thus give
- * more than 10 parameters total. But gcc can
- * only handle up to 10 parameters at present :-(
- */
- );
- return;
- }
- #endif
-
- if (effects) {
- register u_char andmask, xormask, ch;
- register int bold;
-
- andmask = (conp->vc_intensity == 0) ? 0x55 : 0xff;
- xormask = (conp->vc_reverse ^ conp->vc_decscnm) ? 0xff : 0;
- bold = (conp->vc_intensity == 2);
-
- while (count--) {
- c = *(s++);
- if (!FONT_CNV(c)) continue;
-
- dest = dest0++;
- cdat = p->fontdata + (c * p->fontheight);
-
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
- ch = *cdat++;
- if (rows == 0 && conp->vc_underline) ch = 0xff;
- ch = (ch & andmask) ^ xormask;
- if (bold) ch |= ch >> 1;
- *dest = ch;
- }
- }
- }
- else {
-
- while (count--) {
- c = *(s++);
- if (!FONT_CNV(c)) continue;
-
- dest = dest0++;
- cdat = p->fontdata + (c * p->fontheight);
-
- for (rows = p->fontheight ; rows-- ; dest += bytes)
- *dest = *cdat++;
- }
- }
- }
-
-
- static void atacon_rev_char_1_plane( struct display *display, int x, int y )
-
- { u_char *p;
- int offs;
- u_short j;
-
- offs = y * display->fontheight * display->bytes_per_row + x;
-
- p = display->bitplane + offs;
- j = display->fontheight - 1;
- __asm__ __volatile__
- ("1: notb %0@ ; addaw %4,%0\n\t"
- "dbra %1,1b"
- : "=a" (p), "=d" (j)
- : "0" (p), "1" (j),
- "d" (display->bytes_per_row)
- );
- }
-
-
-
- #ifdef CONFIG_ATARI_2PLANE
-
- /* ================================================================= */
- /* 2 Plane Functions */
- /* ================================================================= */
-
-
- /* Increment/decrement 2 plane addresses */
-
- #define INC_2P(p) do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0)
- #define DEC_2P(p) do { if ((long)(--(p)) & 1) (p) -= 2; } while(0)
-
- /* Convert a standard 4 bit color to our 2 bit color assignment:
- * If at least two RGB channels are active, the low bit is turned on;
- * The intensity bit (b3) is shifted into b1.
- */
-
- #define COLOR_2P(c) (((c & 7) >= 3 && (c & 7) != 4) | (c & 8) >> 2)
-
-
- static void atacon_bmove_2_plane( register struct display *p,
- int sy, int sx, int dy, int dx,
- int height, int width)
- {
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjancent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- if (sx == 0 && dx == 0 && width == p->bytes_per_row/2) {
- /* Special (but often used) case: Moving whole lines can be
- * done with memmove()
- */
- mymemmove( p->bitplane + dy * p->bytes_per_row * p->fontheight,
- p->bitplane + sy * p->bytes_per_row * p->fontheight,
- p->bytes_per_row * height * p->fontheight );
- } else {
- register ushort rows, cols;
- register u_char *src;
- register u_char *dst;
- register ushort bytes = p->bytes_per_row;
- register ushort linesize = bytes * p->fontheight;
- unsigned colsize = height * p->fontheight;
- unsigned upwards = (dy < sy) || (dy == sy && dx < sx);
-
- if ((sx & 1) == (dx & 1)) {
- /* odd->odd or even->even */
-
- if (upwards) {
-
- src = p->bitplane + sy * linesize + (sx>>1)*4 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*4 + (dx & 1);
-
- if (sx & 1) {
- memmove_2p_col( dst, src, colsize, bytes );
- src += 3;
- dst += 3;
- --width;
- }
-
- if (width > 1) {
- for( rows = colsize; rows > 0; --rows ) {
- mymemmove( dst, src, (width>>1)*4 );
- src += bytes;
- dst += bytes;
- }
- }
-
- if (width & 1) {
- src -= colsize * bytes;
- dst -= colsize * bytes;
- memmove_2p_col( dst + (width>>1)*4, src + (width>>1)*4,
- colsize, bytes );
- }
- }
- else {
-
- if (!((sx+width-1) & 1)) {
- src = p->bitplane + sy * linesize + ((sx+width-1)>>1)*4;
- dst = p->bitplane + dy * linesize + ((dx+width-1)>>1)*4;
- memmove_2p_col( dst, src, colsize, bytes );
- --width;
- }
-
- src = p->bitplane + sy * linesize + (sx>>1)*4 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*4 + (dx & 1);
-
- if (width > 1) {
- src += colsize * bytes + (sx & 1)*3;
- dst += colsize * bytes + (sx & 1)*3;
- for( rows = colsize; rows > 0; --rows ) {
- src -= bytes;
- dst -= bytes;
- mymemmove( dst, src, (width>>1)*4 );
- }
- }
-
- if (width & 1) {
- memmove_2p_col( dst-3, src-3, colsize, bytes );
- }
-
- }
- }
- else {
- /* odd->even or even->odd */
-
- if (upwards) {
- src = p->bitplane + sy * linesize + (sx>>1)*4 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*4 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_2p_col( dst, src, colsize, bytes );
- INC_2P( src );
- INC_2P( dst );
- }
- }
- else {
- sx += width-1;
- dx += width-1;
- src = p->bitplane + sy * linesize + (sx>>1)*4 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*4 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_2p_col( dst, src, colsize, bytes );
- DEC_2P( src );
- DEC_2P( dst );
- }
- }
- }
-
-
- }
- }
-
-
- static void atacon_clear_2_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width )
- {
- ulong offset;
- register u_char *start;
- register ushort rows;
- register ushort bytes = p->bytes_per_row;
- ushort lines = height * p->fontheight;
- register ulong size;
- u_long cval;
- u_short pcval;
-
- expand2l( COLOR_2P(conp->vc_video_erase_char >> 12), &cval );
-
- if (sx == 0 && width == bytes/2) {
-
- offset = sy * bytes * p->fontheight;
- size = lines * bytes;
- memset_even_2p( p->bitplane+offset, size, cval );
-
- } else {
-
- offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
- start = p->bitplane + offset;
- pcval = expand2w( COLOR_2P(conp->vc_video_erase_char >> 12) );
-
- /* Clears are split if the region starts at an odd column or
- * end at an even column. These extra columns are spread
- * across the interleaved planes. All in between can be
- * cleared by normal mymemclear_small(), because both bytes of
- * the single plane words are affected.
- */
-
- if (sx & 1) {
- memclear_2p_col( start, lines, pcval, bytes );
- start += 3;
- width--;
- }
-
- if (width & 1) {
- memclear_2p_col( start + (width>>1)*4, lines, pcval, bytes );
- width--;
- }
-
- if (width) {
- for( rows = lines; rows-- ; start += bytes )
- memset_even_2p( start, width*2, cval );
- }
- }
- }
-
-
- static void atacon_putc_2_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode)
-
- { register u_char *dest;
- register u_char *cdat;
- register ushort rows;
- register u_short bytes = p->bytes_per_row;
- ulong eorx, fgx, bgx, fdx;
-
- if (!FONT_CNV(c)) return;
-
- dest = p->bitplane + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
-
- fgx = expand2w( COLOR_2P(conp->vc_attr) );
- bgx = expand2w( COLOR_2P(conp->vc_attr >> 4) );
- eorx = fgx ^ bgx;
-
- for( rows = p->fontheight ; rows-- ; dest += bytes ) {
- fdx = dup2w( *cdat++ );
- __asm__ __volatile__ ( "movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx) );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__ ( "movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest-bytes), "d" (fgx) );
- }
- }
-
-
- static void atacon_putcs_2_plane( struct condata *conp, struct
- display *p, const char *s,
- int count, int y, int x, int mode)
-
- { register u_char *dest, *dest0;
- register u_char *cdat, c;
- register ushort rows;
- register u_short bytes;
- ulong eorx, fgx, bgx, fdx;
-
- bytes = p->bytes_per_row;
- dest0 = p->bitplane + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
- fgx = expand2w( COLOR_2P(conp->vc_attr) );
- bgx = expand2w( COLOR_2P(conp->vc_attr >> 4) );
- eorx = fgx ^ bgx;
-
- while( count-- > 0 ) {
-
- c = *s++;
- if (!FONT_CNV(c)) continue;
- cdat = p->fontdata + (c * p->fontheight);
-
- for( rows = p->fontheight, dest = dest0; rows-- ; dest += bytes ) {
- fdx = dup2w( *cdat++ );
- __asm__ __volatile__ ( "movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx) );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__ ( "movepw %1,%0@(0)" : /* no outputs */
- : "a" (dest-bytes), "d" (fgx) );
- }
-
- INC_2P(dest0);
- }
- }
-
-
- static void atacon_rev_char_2_plane( struct display *display, int x, int y )
-
- { u_char *p;
- u_short j;
-
- p = display->bitplane +
- y * display->fontheight * display->bytes_per_row +
- (x>>1)*4 + (x & 1);
- j = display->fontheight - 1;
-
- __asm__ __volatile__
- /* This should really obey the individual character's
- * background and foreground colors instead of simply
- * inverting.
- */
- ("1: notb %0@ ; notb %0@(2)\n\t"
- "addaw %4,%0\n\t"
- "dbra %1,1b"
- : "=a" (p), "=d" (j)
- : "0" (p), "1" (j), "d" (display->bytes_per_row)
- );
- }
-
-
- #endif /* CONFIG_ATARI_2PLANE */
-
-
-
- #ifdef CONFIG_ATARI_4PLANE
-
- /* ================================================================= */
- /* 4 Plane Functions */
- /* ================================================================= */
-
-
- /* Increment/decrement 4 plane addresses */
-
- #define INC_4P(p) do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
- #define DEC_4P(p) do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
-
-
- static void atacon_bmove_4_plane( register struct display *p,
- int sy, int sx, int dy, int dx,
- int height, int width)
- {
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjancent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- if (sx == 0 && dx == 0 && width == p->bytes_per_row/4) {
- /* Special (but often used) case: Moving whole lines can be
- * done with memmove()
- */
- mymemmove( p->bitplane + dy * p->bytes_per_row * p->fontheight,
- p->bitplane + sy * p->bytes_per_row * p->fontheight,
- p->bytes_per_row * height * p->fontheight );
- } else {
- register ushort rows, cols;
- register u_char *src;
- register u_char *dst;
- register ushort bytes = p->bytes_per_row;
- register ushort linesize = bytes * p->fontheight;
- unsigned colsize = height * p->fontheight;
- unsigned upwards = (dy < sy) || (dy == sy && dx < sx);
-
- if ((sx & 1) == (dx & 1)) {
- /* odd->odd or even->even */
-
- if (upwards) {
-
- src = p->bitplane + sy * linesize + (sx>>1)*8 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*8 + (dx & 1);
-
- if (sx & 1) {
- memmove_4p_col( dst, src, colsize, bytes );
- src += 7;
- dst += 7;
- --width;
- }
-
- if (width > 1) {
- for( rows = colsize; rows > 0; --rows ) {
- mymemmove( dst, src, (width>>1)*8 );
- src += bytes;
- dst += bytes;
- }
- }
-
- if (width & 1) {
- src -= colsize * bytes;
- dst -= colsize * bytes;
- memmove_4p_col( dst + (width>>1)*8, src + (width>>1)*8,
- colsize, bytes );
- }
- }
- else {
-
- if (!((sx+width-1) & 1)) {
- src = p->bitplane + sy * linesize + ((sx+width-1)>>1)*8;
- dst = p->bitplane + dy * linesize + ((dx+width-1)>>1)*8;
- memmove_4p_col( dst, src, colsize, bytes );
- --width;
- }
-
- src = p->bitplane + sy * linesize + (sx>>1)*8 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*8 + (dx & 1);
-
- if (width > 1) {
- src += colsize * bytes + (sx & 1)*7;
- dst += colsize * bytes + (sx & 1)*7;
- for( rows = colsize; rows > 0; --rows ) {
- src -= bytes;
- dst -= bytes;
- mymemmove( dst, src, (width>>1)*8 );
- }
- }
-
- if (width & 1) {
- memmove_4p_col( dst-7, src-7, colsize, bytes );
- }
-
- }
- }
- else {
- /* odd->even or even->odd */
-
- if (upwards) {
- src = p->bitplane + sy * linesize + (sx>>1)*8 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*8 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_4p_col( dst, src, colsize, bytes );
- INC_4P( src );
- INC_4P( dst );
- }
- }
- else {
- sx += width-1;
- dx += width-1;
- src = p->bitplane + sy * linesize + (sx>>1)*8 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*8 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_4p_col( dst, src, colsize, bytes );
- DEC_4P( src );
- DEC_4P( dst );
- }
- }
- }
-
-
- }
- }
-
-
- static void atacon_clear_4_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width )
- {
- ulong offset;
- register u_char *start;
- register ushort rows;
- register ushort bytes = p->bytes_per_row;
- ushort lines = height * p->fontheight;
- register ulong size;
- u_long cval1, cval2, pcval;
-
- expand4dl( conp->vc_video_erase_char >> 12, &cval1, &cval2 );
-
- if (sx == 0 && width == bytes/4) {
-
- offset = sy * bytes * p->fontheight;
- size = lines * bytes;
- memset_even_4p( p->bitplane+offset, size, cval1, cval2 );
-
- } else {
-
- offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
- start = p->bitplane + offset;
- pcval = expand4l( conp->vc_video_erase_char >> 12 );
-
- /* Clears are split if the region starts at an odd column or
- * end at an even column. These extra columns are spread
- * across the interleaved planes. All in between can be
- * cleared by normal mymemclear_small(), because both bytes of
- * the single plane words are affected.
- */
-
- if (sx & 1) {
- memclear_4p_col( start, lines, pcval, bytes );
- start += 7;
- width--;
- }
-
- if (width & 1) {
- memclear_4p_col( start + (width>>1)*8, lines, pcval, bytes );
- width--;
- }
-
- if (width) {
- for( rows = lines; rows-- ; start += bytes )
- memset_even_4p( start, width*4, cval1, cval2 );
- }
- }
- }
-
-
- static void atacon_putc_4_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode)
- { register u_char *dest;
- register u_char *cdat;
- register ushort rows;
- register u_short bytes = p->bytes_per_row;
- ulong eorx, fgx, bgx, fdx;
-
- if (!FONT_CNV(c)) return;
-
- dest = p->bitplane + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
-
- fgx = expand4l( conp->vc_attr );
- bgx = expand4l( conp->vc_attr >> 4 );
- eorx = fgx ^ bgx;
-
- for( rows = p->fontheight ; rows-- ; dest += bytes ) {
- fdx = dup4l( *cdat++ );
- __asm__ __volatile__ ( "movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx) );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__ ( "movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest-bytes), "d" (fgx) );
- }
- }
-
-
- static void atacon_putcs_4_plane( struct condata *conp, struct
- display *p, const char *s,
- int count, int y, int x, int mode)
- { register u_char *dest, *dest0;
- register u_char *cdat, c;
- register ushort rows;
- register u_short bytes;
- ulong eorx, fgx, bgx, fdx;
-
- bytes = p->bytes_per_row;
- dest0 = p->bitplane + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
- fgx = expand4l( conp->vc_attr );
- bgx = expand4l( conp->vc_attr >> 4 );
- eorx = fgx ^ bgx;
-
- while( count-- > 0 ) {
-
- /* I think, unrolling the loops like in the 1 plane case isn't
- * practicable here, because the body is much longer for 4
- * planes (mostly the dup4l()). I guess, unrolling this would
- * need more than 256 bytes and so exceed the instruction
- * cache :-(
- */
-
- c = *s++;
- if (!FONT_CNV(c)) continue;
- cdat = p->fontdata + (c * p->fontheight);
-
- for( rows = p->fontheight, dest = dest0; rows-- ; dest += bytes ) {
- fdx = dup4l( *cdat++ );
- __asm__ __volatile__ ( "movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx) ^ bgx) );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__ ( "movepl %1,%0@(0)" : /* no outputs */
- : "a" (dest-bytes), "d" (fgx) );
- }
-
- INC_4P(dest0);
- }
- }
-
-
- static void atacon_rev_char_4_plane( struct display *display, int x, int y )
-
- { u_char *p;
- u_short j;
-
- p = display->bitplane +
- y * display->fontheight * display->bytes_per_row +
- (x>>1)*8 + (x & 1);
- j = display->fontheight - 1;
-
- __asm__ __volatile__
- /* This should really obey the individual character's
- * background and foreground colors instead of simply
- * inverting.
- */
- ("1: notb %0@ ; notb %0@(2) ; notb %0@(4) ; notb %0@(6)\n\t"
- "addaw %4,%0\n\t"
- "dbra %1,1b"
- : "=a" (p), "=d" (j)
- : "0" (p), "1" (j), "d" (display->bytes_per_row)
- );
- }
-
-
- #endif /* CONFIG_ATARI_4PLANE */
-
-
-
- #ifdef CONFIG_ATARI_8PLANE
-
- /* ================================================================= */
- /* 8 Plane Functions */
- /* ================================================================= */
-
-
- /* In 8 plane mode, 256 colors would be possible, but only the first
- * 16 are used by the console code (the upper 4 bits are
- * background/unused). For that, the following functions mask off the
- * higher 4 bits of each color.
- */
-
- /* Increment/decrement 8 plane addresses */
-
- #define INC_8P(p) do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0)
- #define DEC_8P(p) do { if ((long)(--(p)) & 1) (p) -= 14; } while(0)
-
-
- static void atacon_bmove_8_plane( register struct display *p,
- int sy, int sx, int dy, int dx,
- int height, int width)
- {
- /* bmove() has to distinguish two major cases: If both, source and
- * destination, start at even addresses or both are at odd
- * addresses, just the first odd and last even column (if present)
- * require special treatment (memmove_col()). The rest between
- * then can be copied by normal operations, because all adjancent
- * bytes are affected and are to be stored in the same order.
- * The pathological case is when the move should go from an odd
- * address to an even or vice versa. Since the bytes in the plane
- * words must be assembled in new order, it seems wisest to make
- * all movements by memmove_col().
- */
-
- if (sx == 0 && dx == 0 && width == p->bytes_per_row/8) {
- /* Special (but often used) case: Moving whole lines can be
- * done with memmove()
- */
- mymemmove( p->bitplane + dy * p->bytes_per_row * p->fontheight,
- p->bitplane + sy * p->bytes_per_row * p->fontheight,
- p->bytes_per_row * height * p->fontheight );
- } else {
- register ushort rows, cols;
- register u_char *src;
- register u_char *dst;
- register ushort bytes = p->bytes_per_row;
- register ushort linesize = bytes * p->fontheight;
- unsigned colsize = height * p->fontheight;
- unsigned upwards = (dy < sy) || (dy == sy && dx < sx);
-
- if ((sx & 1) == (dx & 1)) {
- /* odd->odd or even->even */
-
- if (upwards) {
-
- src = p->bitplane + sy * linesize + (sx>>1)*16 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*16 + (dx & 1);
-
- if (sx & 1) {
- memmove_8p_col( dst, src, colsize, bytes );
- src += 15;
- dst += 15;
- --width;
- }
-
- if (width > 1) {
- for( rows = colsize; rows > 0; --rows ) {
- mymemmove( dst, src, (width>>1)*16 );
- src += bytes;
- dst += bytes;
- }
- }
-
- if (width & 1) {
- src -= colsize * bytes;
- dst -= colsize * bytes;
- memmove_8p_col( dst + (width>>1)*16, src + (width>>1)*16,
- colsize, bytes );
- }
- }
- else {
-
- if (!((sx+width-1) & 1)) {
- src = p->bitplane + sy * linesize + ((sx+width-1)>>1)*16;
- dst = p->bitplane + dy * linesize + ((dx+width-1)>>1)*16;
- memmove_8p_col( dst, src, colsize, bytes );
- --width;
- }
-
- src = p->bitplane + sy * linesize + (sx>>1)*16 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*16 + (dx & 1);
-
- if (width > 1) {
- src += colsize * bytes + (sx & 1)*15;
- dst += colsize * bytes + (sx & 1)*15;
- for( rows = colsize; rows > 0; --rows ) {
- src -= bytes;
- dst -= bytes;
- mymemmove( dst, src, (width>>1)*16 );
- }
- }
-
- if (width & 1) {
- memmove_8p_col( dst-15, src-15, colsize, bytes );
- }
-
- }
- }
- else {
- /* odd->even or even->odd */
-
- if (upwards) {
- src = p->bitplane + sy * linesize + (sx>>1)*16 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*16 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_8p_col( dst, src, colsize, bytes );
- INC_8P( src );
- INC_8P( dst );
- }
- }
- else {
- sx += width-1;
- dx += width-1;
- src = p->bitplane + sy * linesize + (sx>>1)*16 + (sx & 1);
- dst = p->bitplane + dy * linesize + (dx>>1)*16 + (dx & 1);
- for( cols = width; cols > 0; --cols ) {
- memmove_8p_col( dst, src, colsize, bytes );
- DEC_8P( src );
- DEC_8P( dst );
- }
- }
- }
-
-
- }
- }
-
-
- static void atacon_clear_8_plane( struct condata *conp, register struct
- display *p, int sy, int sx, int height,
- int width )
- {
- ulong offset;
- register u_char *start;
- register ushort rows;
- register ushort bytes = p->bytes_per_row;
- ushort lines = height * p->fontheight;
- register ulong size;
- u_long cval1, cval2, cval3, cval4, pcval1, pcval2;
-
- expand8ql( (conp->vc_video_erase_char >> 12) & 0xf,
- &cval1, &cval2, &cval3, &cval4 );
-
- if (sx == 0 && width == bytes/8) {
-
- offset = sy * bytes * p->fontheight;
- size = lines * bytes;
- memset_even_8p( p->bitplane+offset, size, cval1, cval2, cval3, cval4 );
-
- } else {
-
- offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
- start = p->bitplane + offset;
- expand8dl( (conp->vc_video_erase_char >> 12) & 0xf, &pcval1, &pcval2 );
-
- /* Clears are split if the region starts at an odd column or
- * end at an even column. These extra columns are spread
- * across the interleaved planes. All in between can be
- * cleared by normal mymemclear_small(), because both bytes of
- * the single plane words are affected.
- */
-
- if (sx & 1) {
- memclear_8p_col( start, lines, pcval1, pcval2, bytes );
- start += 7;
- width--;
- }
-
- if (width & 1) {
- memclear_8p_col( start + (width>>1)*16, lines, pcval1,
- pcval2, bytes );
- width--;
- }
-
- if (width) {
- for( rows = lines; rows-- ; start += bytes )
- memset_even_8p( start, width*8, cval1, cval2, cval3, cval4 );
- }
- }
- }
-
-
- static void atacon_putc_8_plane( struct condata *conp, struct display *p,
- int c, int y, int x, int mode)
- { register u_char *dest;
- register u_char *cdat;
- register ushort rows;
- register u_short bytes = p->bytes_per_row;
- ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
-
- if (!FONT_CNV(c)) return;
-
- dest = p->bitplane + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
- cdat = p->fontdata + (c * p->fontheight);
-
- expand8dl( conp->vc_attr & 0x0f, &fgx1, &fgx2 );
- expand8dl( (conp->vc_attr >> 4) & 0x0f, &bgx1, &bgx2 );
- eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
-
- for( rows = p->fontheight ; rows-- ; dest += bytes ) {
- fdx = dup4l( *cdat++ );
- __asm__ __volatile__
- ( "movepl %1,%0@(0)\n\t"
- "movepl %2,%0@(8)"
- : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
- "d" ((fdx & eorx2) ^ bgx2)
- );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__
- ( "movepl %1,%0@(0)\n\t"
- "movepl %2,%0@(8)"
- : /* no outputs */
- : "a" (dest-bytes), "d" (fgx1), "d" (fgx2)
- );
- }
- }
-
-
- static void atacon_putcs_8_plane( struct condata *conp, struct
- display *p, const char *s,
- int count, int y, int x, int mode)
-
- { register u_char *dest, *dest0;
- register u_char *cdat, c;
- register ushort rows;
- register u_short bytes;
- ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
-
- bytes = p->bytes_per_row;
- dest0 = p->bitplane + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
-
- expand8dl( conp->vc_attr & 0x0f, &fgx1, &fgx2 );
- expand8dl( (conp->vc_attr >> 4) & 0x0f, &bgx1, &bgx2 );
- eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
-
- while( count-- > 0 ) {
-
- /* I think, unrolling the loops like in the 1 plane case isn't
- * practicable here, because the body is much longer for 4
- * planes (mostly the dup4l()). I guess, unrolling this would
- * need more than 256 bytes and so exceed the instruction
- * cache :-(
- */
-
- c = *s++;
- if (!FONT_CNV(c)) continue;
- cdat = p->fontdata + (c * p->fontheight);
-
- for( rows = p->fontheight, dest = dest0; rows-- ; dest += bytes ) {
- fdx = dup4l( *cdat++ );
- __asm__ __volatile__
- ( "movepl %1,%0@(0)\n\t"
- "movepl %2,%0@(8)"
- : /* no outputs */
- : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
- "d" ((fdx & eorx2) ^ bgx2)
- );
- }
-
- if (conp->vc_underline) {
- __asm__ __volatile__
- ( "movepl %1,%0@(0)\n\t"
- "movepl %2,%0@(8)"
- : /* no outputs */
- : "a" (dest-bytes), "d" (fgx1), "d" (fgx2)
- );
- }
-
- INC_8P(dest0);
- }
- }
-
-
- static void atacon_rev_char_8_plane( struct display *display, int x, int y )
-
- { u_char *p;
- u_short j;
-
- p = display->bitplane +
- y * display->fontheight * display->bytes_per_row +
- (x>>1)*16 + (x & 1);
- j = display->fontheight - 1;
-
- __asm__ __volatile__
- /* This should really obey the individual character's
- * background and foreground colors instead of simply
- * inverting. For 8 plane mode, only the lower 4 bits of the
- * color are inverted, because only that color registers have
- * been set up.
- */
- ("1: notb %0@ ; notb %0@(2) ; notb %0@(4) ; notb %0@(6)\n\t"
- "addaw %4,%0\n\t"
- "dbra %1,1b"
- : "=a" (p), "=d" (j)
- : "0" (p), "1" (j), "d" (display->bytes_per_row)
- );
- }
-
-
- #endif /* CONFIG_ATARI_8PLANE */
-
-
- /* ================================================================= */
- /* Cursor Functions */
- /* ================================================================= */
-
-
- #ifdef CURSOR_DELAY_TIMER
-
- static void atacon_curtimfunc( unsigned long _disp )
-
- { struct display *display = (struct display *)_disp;
-
- /* Do nothing if cursor is already drawn (how?) or the active
- * console has been changed.
- */
- if (cursor_drawn || display != &disp[fg_console])
- return;
-
- atacon_rev_char( display, display->cursor_x, display->cursor_y );
- cursor_drawn = 1;
-
- }
-
- #endif
-
- #ifdef CURSOR_DELAY_VBL
-
- static void atacon_vbl_handler( struct intframe *fp, void *dummy )
-
- { struct display *display;
-
- if (!cursor_on) return;
-
- if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
- /* Here no check is possible for console changing. The console
- * switching code should set vbl_cursor_cnt to an appropriate value.
- */
- display = &disp[fg_console];
- display->dispsw->rev_char( display, display->cursor_x,
- display->cursor_y );
- cursor_drawn ^= 1;
- vbl_cursor_cnt = cursor_blink_rate;
- }
- }
-
- #endif
-
-
- static int atacon_cursor (struct condata *conp, int mode)
-
- { struct display *display = &disp[conp - vc_cons];
-
- switch( mode ) {
-
- case CM_ERASE:
- if (cursor_drawn)
- display->dispsw->rev_char( display, display->cursor_x,
- display->cursor_y );
- display->cursor_x = conp->vc_x;
- display->cursor_y = conp->vc_y;
- CURSOR_UNDRAWN();
- #ifdef CURSOR_DELAY_VBL
- cursor_on = 0;
- #endif
- break;
-
- case CM_MOVE:
- case CM_DRAW:
- if (cursor_drawn)
- display->dispsw->rev_char( display, display->cursor_x,
- display->cursor_y);
- CURSOR_UNDRAWN();
-
- display->cursor_x = conp->vc_x;
- display->cursor_y = conp->vc_y;
-
- #ifdef CURSOR_DELAY_TIMER
- del_timer( &atacon_cursor_timer );
- atacon_cursor_timer.expires = CURSOR_DRAW_DELAY;
- atacon_cursor_timer.data = (unsigned long)display;
- add_timer( &atacon_cursor_timer );
- #endif
- #ifdef CURSOR_DELAY_VBL
- vbl_cursor_cnt = CURSOR_DRAW_DELAY;
- cursor_on = 1;
- #endif
- break;
- }
-
- return( 0 );
- }
-
- /*
- * The console "switch" structure for the Atari native console
- */
-
-
- struct consw ata_con =
- {
- atacon_init, atacon_deinit, atacon_clear, atacon_putc, atacon_putcs,
- atacon_cursor, atacon_scroll, atacon_bmove, atacon_switch
- };
-
-